#pragma once

//////////////////////////////////////////////////////////////////////////
/// The TaskManager handles everything related to the distribution and
/// execution of tasks that need to be done inside the thread the graphics
/// was created in. It schedules the execution and splits the work onto
/// multiple frames. Though the implementing task is responsible to keep
/// its work during one frame low to make sure the FPS ain't touched
/// that much.
//////////////////////////////////////////////////////////////////////////
class TaskManager
{
	std::set<IGraphicsTask*> mActiveTasks;
	std::set<IGraphicsTask*> mPriorityTasks;
	Mutex mTaskLock;
	ui32 mCurFrame;
public:
	TaskManager() {
		mCurFrame = 0;
	}

	void executeFrame() {
		MUTEX_LOCK(mTaskLock);

		ui32 i = 0;
		for( ; i < 3 && mPriorityTasks.size(); ++i) {
			auto task = mPriorityTasks.begin();
			if((*task)->execute()) {
				(*task)->finish();
				mPriorityTasks.erase(task);
				continue;
			}
		}

		for( ; i < 3 && mActiveTasks.size(); ++i) {
			auto task = mActiveTasks.begin();
			if((*task)->execute()) {
				(*task)->finish();
				mActiveTasks.erase(task);
				continue;
			}
		}
		++mCurFrame;
	}

	void pushTask(IGraphicsTask* pTask) {
		MUTEX_LOCK(mTaskLock);
		if(pTask->isPriorityTask()) {
			if(mPriorityTasks.find(pTask) != mPriorityTasks.end())
				return;

			mPriorityTasks.insert(pTask);
		} else {
			if(mActiveTasks.find(pTask) != mActiveTasks.end())
				return;

			mActiveTasks.insert(pTask);
		}
	}
};